#ifndef _CONNECTION_H_INCLUDED_
#define _CONNECTION_H_INCLUDED_
#include <list>
#include <mutex>
#include <memory>
#include "Socket.h"
#include "X7.h"
#include "responder.h"
/* 连接事件 */
const int UNUSED = 0; //未使用的，可以分配的连接
const int TOBEUSED = 1; //已经被分配的连接
const int READ_TYPE = 1 << 1; //分配了读事件的连接
const int WRITE_TYPE = 1 << 2; //分配了写事件的连接
const int DEFAULT_CONNECTION_POOL_SIZE = 100;

struct connection_t
{
    int fd = -1;
    int type = UNUSED;
    std::shared_ptr<X7> reader; //连接的读事件处理协议对象
    std::shared_ptr<responder> writer; //连接的写事件处理对象
    bool isReady = false;
    std::mutex writerLock; //写锁，用于避免多线程对同个连接进行写操作造成的数据紊乱
    socklen_t addrlen;
    sockaddr_in addr;
    connection_t():writerLock(){
       memset(&addrlen, 0, sizeof(addrlen));
    }
    void setConnnection(int _fd, int _type, X7* _reader, responder* _writer , bool d){
        fd = _fd;
        memset(&addrlen, 0, sizeof(addrlen));
        if(_type >= UNUSED && _type <= WRITE_TYPE)
            type = _type;
        reader.reset(_reader);
        writer.reset(_writer);
        isReady = d;
    }
};

//线程不安全的连接池
class connectionPool
{
private:
    using it_t = std::list<connection_t>::iterator;
    std::list<connection_t> connections;
    int numsAvailable;
public:
    connectionPool():
    connections(DEFAULT_CONNECTION_POOL_SIZE), numsAvailable(DEFAULT_CONNECTION_POOL_SIZE){}
    inline connection_t* getFreeConnection()//从连接池中获取一个空连接
    {
        if(numsAvailable == 0){
            connections.emplace_back();
            numsAvailable++;
        }
        for(it_t it = connections.begin(); it != connections.end(); it++){
            if(it->type == UNUSED){
                it->type = TOBEUSED;
                numsAvailable--;
                return (connection_t*)&(*it);
            }
        }
    }
    //to do: 回收reader
    inline void returnConnection(connection_t* theConnection)//向连接池归还连接
    {
        theConnection->reader.reset();//释放reader
        theConnection->writer.reset();//释放writer
        theConnection->setConnnection(-1, UNUSED, nullptr,nullptr,false);
        numsAvailable++;
    } 
};

#endif